<?php

namespace Xrfg\Api\Trading\Spot\Jobs;

use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Xrfg\Api\Trading\Spot\Events\KlineSavedEvent;
use Xrfg\Core\Trading\Spot\Models\Kline;
use Xrfg\Core\Trading\Spot\Models\Trade;
use Xrfg\Api\Trading\Spot\Repositories\klineRepository;

class KlineJob implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    protected $trade;

    public function __construct(Trade $trade)
    {
        $this->trade = $trade;
    }

    public function handle()
    {
        foreach (Kline::$types as $type) {
            $this->update($this->trade->symbol, $type);
        }
    }

    /**
     * @param $symbol
     * @param $type
     */
    private function update($symbol, $type)
    {
        $kline = new Kline($symbol, $type);
        if (1440 == $type) { // 日线，需要特殊处理，因为时间戳起点：北京时间1970年01月01日08时00分00秒
            $openTime = today()->timestamp;
        } else if (10080 == $type) { // 周线，需要特殊处理，因为时间戳起点：北京时间1970年01月01日08时00分00秒
            $openTime = today()->subDays(today()->weekday())->timestamp;
        } else {
            $openTime = floor(time() / (60 * $type)) * 60 * $type;
        }
        // 查询当前时刻K线数据是否存在，不存在则创建，存在则更新
        try {
            /** @var Kline $item */
            $item = $kline->where('time_open', $openTime)->first();
        } catch (Exception $exception) {
            if ('42S02' == $exception->getCode()) {
                (new KlineRepository())->createTable($kline->getTable());
            } else {
                Log::debug($exception);
            }
        }
        if (isset($item) and !is_null($item)) { // 存在
            $item->symbol = $symbol;
            $item->type = $type;
            $item->setTable($kline->getTable());
            $item->price_close = $this->trade->price;
            $item->price_high = max($item->price_high, $this->trade->price);
            $item->price_low = min($item->price_low, $this->trade->price);
            $item->trades_number += $this->trade->number;
            $item->trades_total += $this->trade->price * $this->trade->number;
            ++$item->trades_count;
            $item->save();
        } else { // 不存在
            $item = $kline;
            $item->time_open = $openTime;
            $item->time_close = $openTime + 60 * $type;
            $item->price_open = $this->trade->price;
            $item->price_close = $this->trade->price;
            $item->price_high = $this->trade->price;
            $item->price_low = $this->trade->price;
            $item->trades_number = $this->trade->number;
            $item->trades_total = $this->trade->number * $this->trade->price;
            $item->trades_count = 1;
            $item->save();
        }
        event(new KlineSavedEvent($item));
    }
}
